#include "base/base_buffer.h"
#include "base/channel.h"
#include "base/eventloop.h"
#include "base/log.h"
#include "util/mempool.h"
#include "net/connect.h"

#include <sys/socket.h>
#include <vector>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <cstring>

#include "net/buffer.h"
namespace net_tools::net
{

#define to_c(x) reinterpret_cast<char *>(x)
  net_tools::base::Memorypool *Buffer::mempool_ = nullptr;
  __thread Buffer_reader *Buffer::buffer_reader_ = nullptr;

  Buffer::Buffer(net_tools::Eventloop *eventloop, Connect *connect)
      : eventloop_(eventloop),
        connect_(connect),
        fd_(0),
        send_all_(true),
        user_want_close_(false),
        still_have_(false),
        recv_head_len_(0),
        residue_len_(0),
        last_time_head_len_data_len_(0),
        head_send_buf_(nullptr),
        head_recv_buf_(nullptr),
        now_send_buf_(nullptr),
        now_recv_buf_(nullptr){};
  void Buffer::Init_channel(net_tools::base::Channel *channel)
  {
    channel_ = channel;
    fd_ = channel_->Get_listenfd();

    head_send_buf_ = Get_new_buf(2);
    now_send_buf_ = head_send_buf_;

    head_recv_buf_ = Get_new_buf(1);
    now_recv_buf_ = head_recv_buf_;

    head_recv_buf_->Insert_next(Get_new_buf(1));
  };
  net_tools::base::Base_buffer *Buffer::Get_new_buf(int size)
  {
    return new net_tools::base::Base_buffer(size);
  };

  uint32_t Buffer::Peak()
  {
    if (!residue_len_)
    {
      Analyze_head();
    }
    return residue_len_;
  };

  void Buffer::Read_buf_clear()
  {
    if (head_recv_buf_->Is_empty())
    {
      if (head_recv_buf_ != now_recv_buf_)
      {
        // 如果不是当前的写区 则后面一定有东西没读
        head_recv_buf_->Clear_index();
        head_recv_buf_ = head_recv_buf_->Get_next();
      }
      else
      {
        if (!still_have_)
        {
          // 如果是当前的写区但是这次读写后面没东西了
          head_recv_buf_->Clear_index();
        }
      }
    }
  };
  void Buffer::Analyze_head()
  {
    if (head_recv_buf_->Get_read_residue() < _C::NET_BUFFER_LENDATA_SIZE)
    { // 跨区
      char buf[4] = {};
      int last_data_len = head_recv_buf_->Get_read_residue();

      memcpy(buf, (*head_recv_buf_)[0], last_data_len);
      head_recv_buf_->Clear_index();
      head_recv_buf_ = head_recv_buf_->Get_next();
      memcpy(buf + last_data_len, (*head_recv_buf_)[0], _C::NET_BUFFER_LENDATA_SIZE - last_data_len);
      head_recv_buf_->Read_append(_C::NET_BUFFER_LENDATA_SIZE - last_data_len);
      residue_len_ = *reinterpret_cast<uint32_t *>(buf);
      Read_buf_clear();
    }
    else
    { // 没跨区
      residue_len_ = *reinterpret_cast<uint32_t *>((*head_recv_buf_)[0]);
      head_recv_buf_->Read_append(_C::NET_BUFFER_LENDATA_SIZE);
      Read_buf_clear();
    }
  };

  int Buffer::Read(void *buf, uint32_t max_size)
  {
    if (!residue_len_)
    { // 第一次收到这个包
      Analyze_head();
    }
    uint32_t read_len = 0; //这次读的长度
    while (residue_len_ > 0)
    {
      uint32_t now_write = residue_len_ > head_recv_buf_->Get_read_residue() ? head_recv_buf_->Get_read_residue() : residue_len_;
      now_write = now_write > max_size - read_len ? max_size - read_len : now_write;
      memcpy(to_c(buf) + read_len, (*head_recv_buf_)[0], now_write);
      residue_len_ -= now_write;
      head_recv_buf_->Read_append(now_write);
      read_len += now_write;
      Read_buf_clear();
      if (read_len == max_size)
      { //用户提供的缓冲区满了
        return max_size;
      }
    }
    return read_len;
  };

  Buffer_reader *Buffer::Read()
  {
    Analyze_head();
    // buffer_reader_->Init(this);
    return buffer_reader_;
  };

  void Buffer::Recv(uint32_t len)
  {
    while (len > 0)
    {
      uint32_t now_write = len > now_recv_buf_->Get_write_residue() ? now_recv_buf_->Get_write_residue() : len;
      now_recv_buf_->Write_append(now_write);
      len -= now_write;
      if (now_recv_buf_->Is_full())
      {
        now_recv_buf_ = now_recv_buf_->Get_next();
      }
    }
  };

  void Buffer::Read_able_callback()
  {
    connect_->Rec_heartbeat();
    iovec iovector[_C::BUFFER_ONCE_READ_CALLBACK_IOVEC_SIZE];
    int read_in_int = Read_from_fd(iovector);
    if (read_in_int <= 0)
    {
      return;
    }
    uint32_t read_in = static_cast<uint32_t>(read_in_int);
    read_in -= Build_head(read_in);
    while (read_in)
    {
      if (recv_head_len_ > 0)
      { //还有数据没读完
        uint32_t now_write = recv_head_len_ > read_in ? read_in : recv_head_len_;
        recv_head_len_ -= now_write;
        read_in -= now_write;
        Recv(now_write);
        if (recv_head_len_ == 0)
        { //收到整包
          still_have_ = static_cast<bool>(read_in);
          read_callback_(connect_);
          // buffer_reader_->Read_all();
          read_in -= Build_head(read_in);
        }
      }
      else if (recv_head_len_ == 0)
      { //收到心跳包
        read_in -= Build_head(read_in);
      }
    }
  };

  int Buffer::Read_from_fd(iovec *iovector)
  {
    int iovector_number = 0;
    net_tools::base::Base_buffer *now_buf = now_recv_buf_;
    for (; iovector_number < _C::BUFFER_ONCE_READ_CALLBACK_IOVEC_SIZE;)
    {
      if (!now_buf->Is_full())
      { // 如果当前区没满 则可以写入
        iovector[iovector_number].iov_base = now_buf->Write_index();
        iovector[iovector_number].iov_len = now_buf->Get_write_residue();
        ++iovector_number;
      }
      now_buf = now_buf->Get_next();
      if (now_buf == head_recv_buf_)
      { //自增后等于头部 没缓冲区了
        now_buf->Insert_pre(Get_new_buf(1));
        now_buf = now_buf->Get_pre();
      }
    }
    int read_in_len = readv(fd_, iovector, iovector_number);
    if (read_in_len <= 0) [[unlikely]]
    { //被瞬间关闭
      Close_callback();
      return -1;
    }
    return read_in_len;
  };

  int Buffer::Build_head(uint32_t len)
  {
    if (recv_head_len_ == 0 && len >= _C::NET_BUFFER_LENDATA_SIZE - last_time_head_len_data_len_)
    { //还没建立起头 且收到的长度够建立起包头
      int len_size = _C::NET_BUFFER_LENDATA_SIZE - last_time_head_len_data_len_;
      if (now_recv_buf_->Get_write_index() - last_time_head_len_data_len_ < 0 ||
          now_recv_buf_->Get_write_index() - last_time_head_len_data_len_ > now_recv_buf_->Get_buf_size() - _C::NET_BUFFER_LENDATA_SIZE)
      { // 跨区了
        Recv(len_size);
        int last_buffer_data_len = _C::NET_BUFFER_LENDATA_SIZE - now_recv_buf_->Get_write_index();
        char buf[4] = {};
        net_tools::base::Base_buffer *pre = now_recv_buf_->Get_pre();
        memcpy(buf, pre->Write_index() - last_buffer_data_len, last_buffer_data_len);
        memcpy(buf + last_buffer_data_len, (*now_recv_buf_)[0], now_recv_buf_->Get_write_index());

        recv_head_len_ = *reinterpret_cast<uint32_t *>(buf);
        last_time_head_len_data_len_ = 0;
      }
      else
      { // 没有跨区
        recv_head_len_ = *reinterpret_cast<uint32_t *>(now_recv_buf_->Write_index(-last_time_head_len_data_len_));
        last_time_head_len_data_len_ = 0;
        Recv(len_size);
      }
      return len_size;
    }
    else if (recv_head_len_ == 0)
    { //还没建立起头 长度不够
      last_time_head_len_data_len_ += len;
      Recv(len);
      return len;
    }
    return 0;
  };

  void Buffer::Send()
  {
    int write_in_len = Write_in_fd();
    if (write_in_len == -1)
    {
      return;
    }
    uint32_t write_in = static_cast<uint32_t>(write_in_len);
    for (;;)
    {
      uint32_t len = head_send_buf_->Get_read_residue();
      if (write_in > len)
      {
        //还有 循环队列
        head_send_buf_->Clear_index();
        head_send_buf_ = head_send_buf_->Get_next();
        write_in -= len;
      }
      else if (write_in == len)
      {
        // 最后一个
        head_send_buf_->Clear_index();
        break;
      }
      else
      {
        //等待下一轮发送
        head_send_buf_->Read_append(write_in);
        channel_->Enablewrite();
        eventloop_->Modevent(channel_);
      }
    }
    send_all_ = true;
    channel_->Disablewrite();
    eventloop_->Modevent(channel_);
  };

  void Buffer::Append(void *buf, uint32_t len)
  {
    uint32_t need_write = len;
    uint32_t already_write = 0;
    send_all_ = false;
    while (need_write > 0)
    {
      uint32_t now_write;
      now_write = need_write > now_send_buf_->Get_write_residue() ? now_send_buf_->Get_write_residue() : need_write;
      now_send_buf_->Write(to_c(buf) + already_write, now_write);
      already_write += now_write;
      need_write -= now_write;
      if (now_send_buf_->Is_full() && need_write > 0)
      {
        now_send_buf_ = now_send_buf_->Get_next();
        if (now_send_buf_ == head_send_buf_)
        { // 没区了
          now_send_buf_->Insert_pre(Get_new_buf(1));
          now_send_buf_ = now_send_buf_->Get_pre();
        }
      }
    }
  };

  bool Buffer::Write(net_tools::base::Base_buffer *base_buffer)
  {
    return true;
  };

  bool Buffer::Write(void *buf, uint32_t len)
  {
    if (user_want_close_) [[unlikely]]
    {
      return false;
    }
    if (!send_all_)
    { //缓冲区不为空 之前的还没被发送
      Append(to_c(&len), _C::NET_BUFFER_LENDATA_SIZE);
      Append(buf, len);
      return true;
    }
    else
    { //缓冲区里没东西了 send_all为true
      iovec iovector[2];
      iovector[0].iov_base = &len;
      iovector[0].iov_len = _C::NET_BUFFER_LENDATA_SIZE;
      iovector[1].iov_base = buf;
      iovector[1].iov_len = len;
      int write_in_len = writev(fd_, iovector, 2);
      if (write_in_len == -1) [[unlikely]]
      {
        if (errno != EWOULDBLOCK)
        { // 不是满了的原因
          Clean_buffer();
          close_callback_(connect_);
          return false;
        }
        else
        {
          write_in_len = 0;
        }
      }
      uint32_t already_write = static_cast<uint32_t>(write_in_len);
      if (already_write < len + _C::NET_BUFFER_LENDATA_SIZE)
      { // 还有东西没写完
        if (already_write < _C::NET_BUFFER_LENDATA_SIZE) [[unlikely]]
        { //如果连头都没写完
          Append(to_c(&len) + already_write, _C::NET_BUFFER_LENDATA_SIZE - already_write);
          already_write = _C::NET_BUFFER_LENDATA_SIZE;
        }
        Append(to_c(buf) + already_write - _C::NET_BUFFER_LENDATA_SIZE, len + _C::NET_BUFFER_LENDATA_SIZE - already_write);
        channel_->Enablewrite();
        eventloop_->Modevent(channel_);
      }
      return true;
    }
  };

  int Buffer::Write_in_fd()
  {
    iovec iovector[_C::BUFFER_ONCE_WRITE_CALLBACK_IOVEC_SIZE];
    int iovector_number = 0;
    net_tools::base::Base_buffer *now_buf = head_send_buf_;
    for (; iovector_number < _C::BUFFER_ONCE_WRITE_CALLBACK_IOVEC_SIZE;)
    {
      iovector[iovector_number].iov_base = (*now_buf)[0];
      iovector[iovector_number].iov_len = now_buf->Get_read_residue();
      ++iovector_number;
      if (!now_buf->Is_full())
      { //不满 没数据了
        break;
      }
      now_buf = now_buf->Get_next();
    }
    int write_in_len = writev(fd_, iovector, iovector_number);
    if (write_in_len == -1) [[unlikely]]
    { //fd_ 被瞬间关闭
      Close_callback();
      return -1;
    }
    return write_in_len;
  };

  void Buffer::Write_able_callback()
  {
    int write_in_len = Write_in_fd();
    if (write_in_len == -1)
    {
      return;
    }
    uint32_t write_in = static_cast<uint32_t>(write_in_len);
    if (write_in == 0)
    {
      return;
    }
    for (;;)
    {
      uint32_t len = head_send_buf_->Get_read_residue();
      if (write_in > len)
      {
        //还有 循环队列
        head_send_buf_->Clear_index();
        head_send_buf_ = head_send_buf_->Get_next();
        write_in -= len;
      }
      else if (write_in == len)
      {
        head_send_buf_->Clear_index();
        if (head_send_buf_ != now_send_buf_)
        {
          // 不是最后一个 恰巧写完
          head_send_buf_ = head_send_buf_->Get_next();
          write_in -= len;
          continue;
        }
        if (user_want_close_)
        {
          User_want_close();
          return;
        }
        break;
      }
      else
      {
        //等待下一轮发送
        head_send_buf_->Read_append(write_in);
        return;
      }
    }
    send_all_ = true;
    channel_->Disablewrite();
    eventloop_->Modevent(channel_);
  };

  void Buffer::Close()
  {
    //用户想关闭了 要把用户里的包都发完
    if (!send_all_)
    { //还没发完 已经监听可写
      user_want_close_ = true;
    }
    else
    {
      User_want_close();
    }
  };
  void Buffer::Close_right_now()
  {
    User_want_close();
  };

  void Buffer::Clean_buffer()
  {
    if (head_send_buf_)
    {
      for (net_tools::base::Base_buffer *begin = head_send_buf_->Get_next(); begin != head_send_buf_; begin = begin->Get_next())
      {
        delete begin;
      }
      delete head_send_buf_;
    }
    if (head_recv_buf_)
    {
      for (net_tools::base::Base_buffer *begin = head_recv_buf_->Get_next(); begin != head_recv_buf_; begin = begin->Get_next())
      {
        delete begin;
      }
      delete head_recv_buf_;
    }
    head_send_buf_ = nullptr;
    head_recv_buf_ = nullptr;
    now_recv_buf_ = nullptr;
    now_send_buf_ = nullptr;
    send_all_ = true;
    user_want_close_ = false;
    still_have_ = false;
    recv_head_len_ = 0;
    residue_len_ = 0;
    last_time_head_len_data_len_ = 0;
    NT_LOG_INFO << "clean buffer" << NT_LOG_ENDL;
  };
  void Buffer::Close_callback()
  {
    NT_LOG_TRACE << "Close_call_back" << NT_LOG_ENDL;
    Clean_buffer();
    close_callback_(connect_);
  };

  void Buffer::User_want_close()
  {
    Clean_buffer();
    user_want_close_callback_(connect_);
  };

  void Buffer::Set_able_read_callback(connect_func cb)
  {
    read_callback_ = std::move(cb);
  };
  void Buffer::Set_able_close_callback(connect_func cb)
  {
    close_callback_ = std::move(cb);
  };
  void Buffer::Set_able_user_close_callback(connect_func cb)
  {
    user_want_close_callback_ = std::move(cb);
  };

} // namespace net_tools::net